﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.model.Instance;
using l1cs.server.serverpackets;
using System.Threading;

namespace l1cs.server.model
{
    public class L1GroundInventory : L1Inventory
    {
        private Timer _timer;

        //private Dictionary <int, DeletionTimer> _reservedTimers = new Dictionary<int, DeletionTimer>();
        private static Object lockobj = new Object();

        //private class DeletionTimer {//extends TimerTask {
        private L1ItemInstance _item;

        //public DeletionTimer(L1ItemInstance item) {
        //    _item = item;
        //}

        //@Override
        public void L1GroundInventoryTimerSub( object state )
        {
            lock ( L1GroundInventory.lockobj )
            {
                if ( !_items.Contains( _item ) )
                {// 拾われたタイミングによってはこの条件を満たし得る
                    return; // 既に拾われている
                }
                removeItem( _item );
            }
        }
        //}

        private void setTimer( L1ItemInstance item )
        {
            if ( string.Compare( Config.ALT_ITEM_DELETION_TYPE, "std", true ) != 0 )
            {
                return;
            }
            if ( item.getItemId() == 40515 )
            { // 精霊の石
                return;
            }

            //_timer.schedule( new DeletionTimer( item ), Config.ALT_ITEM_DELETION_TIME * 60 * 1000 );
            _timer = new Timer( new TimerCallback( L1GroundInventoryTimerSub ), null,
                Config.ALT_ITEM_DELETION_TIME * 60 * 1000, Timeout.Infinite );
        }

        private void cancelTimer( L1ItemInstance item )
        {
            // TODO 優先度5 地面のアイテムの削除タイマーキャンセルの_reservedTimersに入れているところがない？
            //DeletionTimer timer = _reservedTimers.get( item.getId() );
            //if ( timer == null )
            //{
            //    return;
            //}
            //timer.cancel();
            _timer.Dispose();
        }

        public L1GroundInventory( int objectId, int x, int y, short map )
        {
            setId( objectId );
            setX( x );
            setY( y );
            setMap( map );
            L1World.getInstance().addVisibleObject( this );
        }

        override public void onPerceive( L1PcInstance perceivedFrom )
        {
            foreach ( L1ItemInstance item in getItems() )
            {
                if ( !perceivedFrom.knownsObject( item ) )
                {
                    perceivedFrom.addKnownObject( item );
                    perceivedFrom.sendPackets( new S_DropItem( item ) ); // プレイヤーへDROPITEM情報を通知
                }
            }
        }

        // 認識範囲内にいるプレイヤーへオブジェクト送信
        override public void insertItem( L1ItemInstance item )
        {
            setTimer( item );

            foreach ( L1PcInstance pc in L1World.getInstance().getRecognizePlayer( item ) )
            {
                pc.sendPackets( new S_DropItem( item ) );
                pc.addKnownObject( item );
            }
        }

        // 見える範囲内にいるプレイヤーのオブジェクト更新
        override public void updateItem( L1ItemInstance item )
        {
            foreach ( L1PcInstance pc in L1World.getInstance().getRecognizePlayer( item ) )
            {
                pc.sendPackets( new S_DropItem( item ) );
            }
        }

        // 空インベントリ破棄及び見える範囲内にいるプレイヤーのオブジェクト削除
        override public void deleteItem( L1ItemInstance item )
        {
            cancelTimer( item );
            foreach ( L1PcInstance pc in L1World.getInstance().getRecognizePlayer( item ) )
            {
                pc.sendPackets( new S_RemoveObject( item ) );
                pc.removeKnownObject( item );
            }

            _items.Remove( item );
            if ( _items.Count == 0 )
            {
                L1World.getInstance().removeVisibleObject( this );
            }
        }

        private static Logger _log = Logger.getLogger( typeof( L1PcInventory ).FullName );
    }
}
